home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 3006 / 3006.xpi / components / dhDOMHook.js < prev    next >
Text File  |  2010-01-15  |  8KB  |  241 lines

  1. /******************************************************************************
  2.  *            Copyright (c) 2009 Michel Gutierrez. All Rights Reserved.
  3.  ******************************************************************************/
  4.  
  5. /**
  6.  * Constants.
  7.  */
  8.  
  9. const NS_DOMHOOK_CID = Components.ID("{7e757f8b-0a62-4e65-9339-4b4fd1cb9bcc}");
  10. const NS_DOMHOOK_PROG_ID = "@downloadhelper.net/dom-hook;1";
  11. const DHNS = "http://downloadhelper.net/1.0#";
  12.  
  13. var Util=null;
  14.  
  15. /**
  16. * Object constructor
  17. */
  18. function Hook() {
  19.     try {
  20.         //dump("[Hook] constructor\n");
  21.         var prefService=Components.classes["@mozilla.org/preferences-service;1"]
  22.                                            .getService(Components.interfaces.nsIPrefService);
  23.         this.pref=prefService.getBranch("dwhelper.");
  24.         this.core=Components.classes["@downloadhelper.net/core;1"].
  25.             getService(Components.interfaces.dhICore);
  26.     } catch(e) {
  27.         dump("[Hook] !!! constructor: "+e+"\n");
  28.     }
  29. }
  30.  
  31. Hook.prototype = {}
  32.  
  33. Hook.prototype.hook=function(document) {
  34.     //dump("[Hook] hook("+document.URL+")\n");
  35.     try {
  36.         var ytInPage=this.pref.getBoolPref("yt-inpage");
  37.         if(ytInPage) {
  38.             this.ytHook(document);
  39.         }
  40.     } catch(e) {
  41.         dump("!!! [Hook] hook("+document.URL+"): "+e+"\n");
  42.     }
  43. }
  44.  
  45. Hook.prototype.ytHook=function(document) {
  46.     if(/^http:\/\/(?:[a-z]+\.)?youtube\.com\//.test(document.URL)) {
  47.         //dump("[Hook] hook(): YouTube page\n");
  48.         var titleH1=Util.xpGetSingleNode(document.documentElement,".//div[@id='watch-vid-title']/h1");
  49.         if(!titleH1) {
  50.             dump("!!! [Hook] hook(): title not found\n");
  51.             return;
  52.         }
  53.         
  54.         var xulNS="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
  55.                 
  56.         var img=document.createElementNS(xulNS,"xul:toolbarbutton");
  57.         img.setAttribute("image","http://www.downloadhelper.net/favicon.ico");
  58.         img.setAttribute("type","menu-button");
  59.         img.style.margin="0px 12px 0px 0px";
  60.         img.style.position="relative";
  61.         img.style.top="-3px";
  62.         
  63.         var menupopup=document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul","xul:menupopup");
  64.         menupopup.setAttribute("position","end_before");
  65.         img.appendChild(menupopup);
  66.  
  67.         var entries=this.core.getEntriesForDocument(document);
  68.         if(entries.length==0) {
  69.             dump("!!! [Hook] ytHook(): no entry for: "+document.URL+"\n");
  70.             return;
  71.         }
  72.         var ytEntry=this.core.cloneEntry(entries.queryElementAt(0,Components.interfaces.nsIProperties));
  73.  
  74.         function Listener(core,entry,processor) {
  75.             this.core=core;
  76.             this.entry=entry;
  77.             this.processor=processor;
  78.         }
  79.         Listener.prototype={
  80.             handleEvent: function(event) {
  81.                 try {
  82.                     if(this.processor.canHandle(this.entry)) {
  83.                         this.updateEntry();
  84.                         this.core.processEntry(this.processor,this.entry);
  85.                     } else {
  86.                         var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
  87.                                                     .getService(Components.interfaces.nsIWindowMediator);
  88.                         var window = wm.getMostRecentWindow("navigator:browser");
  89.                         window.alert(Util.getFText("yt-inpage.unavailable-processor",[this.processor.title],1));
  90.                     }
  91.                 } catch(e) {
  92.                     dump("!!! [Hook] ytHook.handleEvent(): "+e+"\n");
  93.                 }
  94.                 event.stopPropagation(); 
  95.             },
  96.             updateEntry: function() {
  97.                 var pageUrl=Util.getPropsString(this.entry,"page-url");
  98.                 var mediaUrl=null;
  99.                 var fileExtension=null;
  100.                 var i=this.core.getEntries().enumerate();
  101.                 while(i.hasMoreElements()) {
  102.                     var entry=i.getNext().QueryInterface(Components.interfaces.nsIProperties);
  103.                     if(entry.has("media-url") && entry.has("page-url") && entry.has("capture-method") && 
  104.                             Util.getPropsString(entry,"page-url")==pageUrl && 
  105.                             Util.getPropsString(entry,"capture-method")=="network") {
  106.                         mediaUrl=Util.getPropsString(entry,"media-url");
  107.                         fileExtension=Util.getPropsString(entry,"file-extension");
  108.                     }
  109.                 }
  110.                 if(mediaUrl) {
  111.                     this.entry=this.core.cloneEntry(this.entry);
  112.                     Util.setPropsString(this.entry,"media-url",mediaUrl);
  113.                     Util.setPropsString(this.entry,"file-name",Util.getPropsString(this.entry,"base-name")+"."+fileExtension);
  114.                 }
  115.             }
  116.         }
  117.  
  118.         var defProcName=this.pref.getCharPref("yt-inpage.default-processor");
  119.         var defProcessor=null;
  120.         
  121.         var i=this.core.getProcessors().enumerate();
  122.         while(i.hasMoreElements()) {
  123.             var processor=i.getNext().QueryInterface(Components.interfaces.dhIProcessor);
  124.             if(processor.name==defProcName)
  125.                 defProcessor=processor;
  126.             if(processor.canHandle(ytEntry)) {
  127.                 var menuitem=document.createElementNS(xulNS,"xul:menuitem");
  128.                 menuitem.setAttribute("label",processor.title);
  129.                 menuitem.setAttribute("tooltiptext",processor.description);
  130.                 menuitem.QueryInterface(Components.interfaces.nsIDOMNSEventTarget).
  131.                     addEventListener("command",new Listener(this.core,ytEntry,processor),false,false);
  132.                 menupopup.appendChild(menuitem);
  133.             }
  134.         }
  135.         if(defProcessor)
  136.             img.QueryInterface(Components.interfaces.nsIDOMNSEventTarget).
  137.                 addEventListener("command",new Listener(this.core,ytEntry,defProcessor),false,false);
  138.         titleH1.insertBefore(img,titleH1.firstChild);
  139.     }
  140. }
  141.  
  142. Hook.prototype.QueryInterface = function(iid) {
  143.     //dump("[Hook] QueryInterface("+iid+")\n");
  144.     if(
  145.         iid.equals(Components.interfaces.dhIDOMHook) ||
  146.         iid.equals(Components.interfaces.nsISupports)
  147.     ) {
  148.         return this;
  149.     }
  150.     throw Components.results.NS_ERROR_NO_INTERFACE;
  151. }
  152.  
  153. var vHookModule = {
  154.     firstTime: true,
  155.     
  156.     /*
  157.      * RegisterSelf is called at registration time (component installation
  158.      * or the only-until-release startup autoregistration) and is responsible
  159.      * for notifying the component manager of all components implemented in
  160.      * this module.  The fileSpec, location and type parameters are mostly
  161.      * opaque, and should be passed on to the registerComponent call
  162.      * unmolested.
  163.      */
  164.     registerSelf: function (compMgr, fileSpec, location, type) {
  165.  
  166.         if (this.firstTime) {
  167.             this.firstTime = false;
  168.             throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN;
  169.         }
  170.         compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  171.         compMgr.registerFactoryLocation(NS_DOMHOOK_CID,
  172.                                         "Hook",
  173.                                         NS_DOMHOOK_PROG_ID, 
  174.                                         fileSpec,
  175.                                         location,
  176.                                         type);
  177.     },
  178.  
  179.     unregisterSelf: function(compMgr, fileSpec, location) {
  180.         compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  181.         compMgr.unregisterFactoryLocation(NS_DH_DOMHOOK_CID, fileSpec);
  182.     },
  183.  
  184.     /*
  185.      * The GetClassObject method is responsible for producing Factory and
  186.      * SingletonFactory objects (the latter are specialized for services).
  187.      */
  188.     getClassObject: function (compMgr, cid, iid) {
  189.         if (!cid.equals(NS_DOMHOOK_CID)) {
  190.             throw Components.results.NS_ERROR_NO_INTERFACE;
  191.         }
  192.  
  193.         if (!iid.equals(Components.interfaces.nsIFactory)) {
  194.             throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  195.         }
  196.  
  197.         return this.vHookFactory;
  198.     },
  199.  
  200.     /* factory object */
  201.     vHookFactory: {
  202.         /*
  203.          * Construct an instance of the interface specified by iid, possibly
  204.          * aggregating it with the provided outer.  (If you don't know what
  205.          * aggregation is all about, you don't need to.  It reduces even the
  206.          * mightiest of XPCOM warriors to snivelling cowards.)
  207.          */
  208.         createInstance: function (outer, iid) {
  209.             if (outer != null) {
  210.                 throw Components.results.NS_ERROR_NO_AGGREGATION;
  211.             }
  212.     
  213.             if(Util==null) 
  214.                 Util=Components.classes["@downloadhelper.net/util-service;1"]
  215.                     .getService(Components.interfaces.dhIUtilService);
  216.  
  217.             return new Hook().QueryInterface(iid);
  218.         }
  219.     },
  220.  
  221.     /*
  222.      * The canUnload method signals that the component is about to be unloaded.
  223.      * C++ components can return false to indicate that they don't wish to be
  224.      * unloaded, but the return value from JS components' canUnload is ignored:
  225.      * mark-and-sweep will keep everything around until it's no longer in use,
  226.      * making unconditional ``unload'' safe.
  227.      *
  228.      * You still need to provide a (likely useless) canUnload method, though:
  229.      * it's part of the nsIModule interface contract, and the JS loader _will_
  230.      * call it.
  231.      */
  232.     canUnload: function(compMgr) {
  233.         return true;
  234.     }
  235. };
  236.  
  237. function NSGetModule(compMgr, fileSpec) {
  238.     return vHookModule;
  239. }
  240.  
  241.